﻿using System;
using System.Threading;
using System.Collections.Generic;


struct Rock
{
    public int x;
    public int y;
    public char c;
    public ConsoleColor color;
    public int len;
}
class FallingRocksGame
{
    static int livesCount = 5;
    static int playfieldWidth = 15;

    static double speed = 100.0;
    static double acceleration = 0.5;

    static char[] symbols = { '^', '@', '*', '&', '+', '%', '$', '#', '!', '.', ';', '-' };
    static String[] colorNames = ConsoleColor.GetNames(typeof(ConsoleColor));

    static Random randomGenerator = new Random();
    static List<Rock> rocks = new List<Rock>();

    static bool isHit = false;


    static void PrintOnPosition(int x, int y, char c, ConsoleColor color = ConsoleColor.Gray)
    {
        Console.SetCursorPosition(x, y);
        Console.ForegroundColor = color;
        Console.Write(c);
    }
    static void PrintStringOnPosition(int x, int y, string str, ConsoleColor color = ConsoleColor.Gray)
    {
        Console.SetCursorPosition(x, y);
        Console.ForegroundColor = color;
        Console.Write(str);
    }
    static void PrintBoard()
    {
        Console.Clear();
        for (int i = 0; i < Console.WindowHeight; i++)
        {
            PrintOnPosition(playfieldWidth, i, '|', ConsoleColor.White);
        }
        // Print result
        PrintStringOnPosition(playfieldWidth + 3, 4, "Lives:" + livesCount, ConsoleColor.White);
        PrintStringOnPosition(playfieldWidth + 3, 5, "speed:" + speed, ConsoleColor.White);
        // PrintStringOnPosition(playfieldWidth + 3, 6, "accelaration:" + acceleration, ConsoleColor.White);// Redraw playfield
    }

    static void PrintRock(Rock rock)
    {
        for (int i = 0; i < rock.len; i++)
        {
            PrintOnPosition(rock.x + i, rock.y, rock.c, rock.color);
        }

    }

    static void CreateNewRock()
    {
        Rock newRock = new Rock();
        newRock.x = randomGenerator.Next(0, playfieldWidth);
        newRock.y = 0;
        newRock.c = symbols[randomGenerator.Next(0, symbols.Length)];
        newRock.color = (ConsoleColor)Enum.Parse(typeof(ConsoleColor),
            colorNames[randomGenerator.Next(0, colorNames.Length - 1)]);

        int chance = randomGenerator.Next(0, 100);
        if (chance < 5)
        {
            newRock.len = 3;
        }
        else if (chance < 15)
        {
            newRock.len = 2;
        }
        else
        {
            newRock.len = 1;
        }
        if (newRock.x + newRock.len - 1 >= playfieldWidth)
        {
            newRock.x = playfieldWidth - newRock.len;
        }
        rocks.Add(newRock);
    }

    static void SetSpeed()
    {
        speed += acceleration;
        if (speed > 400)
        {
            speed = 400;
        }
    }

    static void CheckHit(Rock nRock, Rock dwarf)
    {

        bool isEqX = false;
        for (int j = 0; j < nRock.len; j++)
        {
            for (int k = 0; k < dwarf.len; k++)
            {
                if (nRock.x + j == dwarf.x + k)
                {
                    isEqX = true;
                    break;
                }
            }
        }

        if (nRock.y == dwarf.y && isEqX)
        {
            livesCount--;
            isHit = true;

            if (livesCount <= 0)
            {
                PrintStringOnPosition(playfieldWidth + 3, 10, "Game Over!", ConsoleColor.Red);
                PrintStringOnPosition(playfieldWidth + 3, 12, "Press [Enter] to exit", ConsoleColor.Red);
                Console.ReadLine();
                Environment.Exit(0);
            }
        }
    }


    static void Main()
    {

        Console.BufferHeight = Console.WindowHeight = 20;
        Console.BufferWidth = Console.WindowWidth = 40;

        Rock dwarf = new Rock();
        dwarf.x = playfieldWidth / 2;
        dwarf.y = Console.WindowHeight - 1;
        dwarf.c = '0';
        dwarf.color = ConsoleColor.White;
        dwarf.len = 1;




        while (true)
        {
            isHit = false;

            SetSpeed();

            CreateNewRock();

            while (Console.KeyAvailable)
            {
                ConsoleKeyInfo pressedKey = Console.ReadKey(true);
                if (pressedKey.Key == ConsoleKey.LeftArrow)
                {
                    if (dwarf.x - 1 >= 0)
                    {
                        dwarf.x = dwarf.x - 1;
                    }
                }
                else if (pressedKey.Key == ConsoleKey.RightArrow)
                {
                    if (dwarf.x + 1 < playfieldWidth)
                    {
                        dwarf.x = dwarf.x + 1;
                    }
                }
            }

            List<Rock> newList = new List<Rock>();


            for (int i = 0; i < rocks.Count; i++)
            {
                Rock rock = rocks[i];

                Rock nRock = new Rock();
                nRock.x = rock.x;
                nRock.y = rock.y + 1;
                nRock.c = rock.c;
                nRock.color = rock.color;
                nRock.len = rock.len;
                if (rock.y + 1 < Console.WindowHeight)
                {
                    newList.Add(nRock);
                }

                //** Check if rock is hitting  us
                CheckHit(nRock, dwarf);

            }
            rocks = newList;


            PrintBoard();

            if (isHit)
            {
                rocks.Clear();
                PrintOnPosition(dwarf.x, dwarf.y, 'X', ConsoleColor.Red);
            }
            else
            {
                PrintOnPosition(dwarf.x, dwarf.y, dwarf.c, dwarf.color);
            }
            foreach (Rock rock in rocks)
            {
                PrintRock(rock);
            }

            Thread.Sleep((int)(600 - speed));

        }

    }




}

